package qc.module.ehs.api.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.*;
import com.deepoove.poi.data.style.BorderStyle;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import qc.common.core.constants.QCAuthConstant;
import qc.common.core.constants.QCConstant;
import qc.common.core.exception.QCPromptException;
import qc.common.core.unify.QCUnifyReturnValue;
import qc.common.core.utils.DateUtil;
import qc.common.core.utils.JsonUtil;
import qc.common.core.utils.QcAttachementFile;
import qc.common.core.utils.QcAttachementsUtil;
import qc.module.ehs.dto.check.CheckTableDto;
import qc.module.ehs.dto.checkrecord.CheckRecordDto;
import qc.module.ehs.dto.report.EhsReportFileUpdateDto;
import qc.module.ehs.dto.task.TaskInfoDto;
import qc.module.ehs.dto.taskexecute.TaskExecuteInfoDto;
import qc.module.ehs.dto.taskitem.TaskItemCheckTableConditionDto;
import qc.module.ehs.dto.taskitem.TaskItemCheckTableResultDto;
import qc.module.ehs.dto.taskitem.TaskItemInfoDto;
import qc.module.ehs.dto.taskitem.TaskItemTransmitDto;
import qc.module.ehs.dto.unit.EhsUnitDto;
import qc.module.ehs.entity.EhsTaskExec;
import qc.module.ehs.entity.EhsTaskItem;
import qc.module.ehs.service.*;
import qc.module.platform.dto.file.FileInfoDto;
import qc.module.platform.dto.file.FileSaveDto;
import qc.module.platform.dto.uac.UacUserInfoDto;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * EHS 安全任务项Controller
 * @author QuCheng Tech
 * @since 2024/11/13
 */
@RefreshScope
@RestController
@RequestMapping("/taskitem")
public class TaskItemController {

    @Autowired
    private EhsTaskItemService service;

    @Autowired
    private EhsTaskInfoService taskInfoService;

    @Autowired
    private EhsTaskExecService taskExecService;

    @Autowired
    private EhsCheckRecordService checkRecordService;

    @Autowired
    private EhsCheckTableService checkTableService;

    @Autowired
    private EhsUnitInfoService unitInfoService;

    @Autowired
    HttpServletRequest request;

    @Autowired
    private RestTemplatePlatform restTemplatePlatform;

    /**
     * 自定义上传目录
     * file.update-path 自定义目录
     * 默认路径为：D://upload
     */
    @Value("${qucheng.upload.path:D://upload}")
    private String UPLOAD_PATH;

    /**
     * 自定义下载目录
     * file.update-path 自定义目录
     * 默认路径为：D://download
     */
    @Value("${qucheng.download.path:D://download}")
    private String DOWNLOAD_PATH;

    /**
     * 获取指定任务的所有分组信息
     * @param id 任务ID
     * @return List<TaskGroupInfoDto>
     * @author QuCheng Tech
     * @since 2024/11/14
     */
    @GetMapping("/get")
    public TaskItemInfoDto getByParam(@RequestParam String id) throws QCPromptException {
        return getTaskItemInfo(id);
    }

    /**
     * 获取指定任务的所有分组信息
     * @param id 任务ID
     * @return List<TaskGroupInfoDto>
     * @author QuCheng Tech
     * @since 2024/11/14
     */
    @GetMapping("/get/{id}")
    public TaskItemInfoDto getByPath(@PathVariable String id) throws QCPromptException {
        return getTaskItemInfo(id);
    }

    TaskItemInfoDto getTaskItemInfo(String taskItemId) throws QCPromptException {
        //由于需要对任务项DTO中是否为转交接收人标记进行赋值，因此需要调用平台接口获取用户ID和作为负责人的部门ID集合
        HttpHeaders headers = new HttpHeaders();
        headers.add(QCAuthConstant.TOKEN_HEADER_KEY, request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY));
        headers.add(QCAuthConstant.PROJECT_CODE_HEADER_KEY, request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY));

        int userId = 0x0;
        int[] deptIds = null;//用户负责的部门ID集合

        UacUserInfoDto userInfo = restTemplatePlatform.getUserInfo(headers);
        if (Objects.nonNull(userInfo)) {
            userId = userInfo.getId().intValue();
        }

        //获取当前用户负责的部门ID
        List<Integer> userLeaderDeptIds = restTemplatePlatform.getProjectDeptLeaders(userId, headers);
        if (userLeaderDeptIds != null && userLeaderDeptIds.size() > 0x0) {
            deptIds = new int[userLeaderDeptIds.size()];
            for (int i = 0; i < userLeaderDeptIds.size(); i++) {
                deptIds[i] = userLeaderDeptIds.get(i).intValue();
            }
        }

        return service.get(taskItemId, userId, deptIds);
    }

    /**
     * 设置指定任务项状态为完成
     * 设置指定的任务项为已完成；需要判断任务项的状态及任务项执行记录的确认状态；
     * @param id 任务项ID
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/11/14
     */
    @RequestMapping(value = "/finish", method = {RequestMethod.POST})
    public String finishByParam(@RequestParam String id) {
        return service.finish(id);
    }

    /**
     * 设置指定任务项状态为完成
     * 设置指定的任务项为已完成；需要判断任务项的状态及任务项执行记录的确认状态；
     * @param id 任务项ID
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/11/14
     */
    @RequestMapping(value = "/finish/{id}", method = {RequestMethod.POST})
    public String finishByPath(@PathVariable String id) {
        return service.finish(id);
    }

    /**
     * 设置指定任务项状态为终止
     * 设置指定的任务项为终止/取消；需要判断任务项的状态及任务项执行记录的确认状态；
     * @param id 任务项ID
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/11/14
     */
    @RequestMapping(value = "/end", method = {RequestMethod.POST})
    public String endByParam(@RequestParam String id) {
        return service.end(id);
    }

    /**
     * 设置指定任务项状态为终止
     * 设置指定的任务项为终止/取消；需要判断任务项的状态及任务项执行记录的确认状态；
     * @param id 任务项ID
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/11/14
     */
    @RequestMapping(value = "/end/{id}", method = {RequestMethod.POST})
    public String endByPath(@PathVariable String id) {
        return service.end(id);
    }

    /**
     * 设置指定任务项状态为继续
     * 设置指定的任务项为继续；需要判断任务项的状态及任务项执行记录的确认状态；
     * @param id 任务项ID
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/11/14
     */
    @RequestMapping(value = "/continue", method = {RequestMethod.POST})
    public String continueByParam(@RequestParam String id) {
        return service.setContinue(id);
    }

    /**
     * 设置指定任务项状态为继续
     * 设置指定的任务项为继续；需要判断任务项的状态及任务项执行记录的确认状态；
     * @param id 任务项ID
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/11/14
     */
    @RequestMapping(value = "/continue/{id}", method = {RequestMethod.POST})
    public String continueByPath(@PathVariable String id) {
        return service.setContinue(id);
    }

    /**
     * 转交指定的任务项
     * <p>
     * 如果当前责任部门/人为空，设置的转交部门/人不能是责任部门/参与组员；
     * 如果当前责任部门/人不为空，设置的转交部门/人不能当前责任部门/人；
     * @param dto 转交DTO
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/11/14
     */
    @RequestMapping(value = "/transmit", method = {RequestMethod.POST})
    public String transmit(@RequestBody TaskItemTransmitDto dto) {
        return service.transmit(dto);
    }

    /***
     *取消转交任务项
     *
     * @param id 任务项ID
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/2/24
     */
    @RequestMapping(value = "/cancel", method = {RequestMethod.POST})
    public String cancelTransmitByParam(@RequestParam String id) {
        return service.cancelTransmit(id, true);
    }

    /***
     *取消转交任务项
     *
     * @param id 任务项ID
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/2/24
     */
    @RequestMapping(value = "/cancel/{id}", method = {RequestMethod.POST})
    public String cancelTransmitByPath(@PathVariable String id) {
        return service.cancelTransmit(id, true);
    }

    /***
     *确认接收转交任务项
     *
     * @param id 任务项ID
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/2/21
     */
    @RequestMapping(value = "/fulfill", method = {RequestMethod.POST})
    public String fulfillTransmitByParam(@RequestParam String id) {
        return service.fulfillTransmit(id);
    }

    /***
     *确认接收转交任务项
     *
     * @param id 任务项ID
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/2/21
     */
    @RequestMapping(value = "/fulfill/{id}", method = {RequestMethod.POST})
    public String fulfillTransmitByPath(@PathVariable String id) {
        return service.fulfillTransmit(id);
    }

    /***
     *拒收转交任务项
     *
     * @param id 任务项ID
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/2/21
     */
    @RequestMapping(value = "/reject", method = {RequestMethod.POST})
    public String rejectTransmitByParam(@RequestParam String id) {
        return service.rejectTransmit(id);
    }

    /***
     *拒收转交任务项
     *
     * @param id 任务项ID
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/2/21
     */
    @RequestMapping(value = "/reject/{id}", method = {RequestMethod.POST})
    public String rejectTransmitByPath(@PathVariable String id) {
        return service.rejectTransmit(id);
    }

    /***
     *退回转交任务项
     *
     * @param id 任务项ID
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/2/25
     */
    @RequestMapping(value = "/return", method = {RequestMethod.POST})
    public String returnTransmitByParam(@RequestParam String id) {
        return service.cancelTransmit(id, false);
    }

    /***
     *退回转交任务项
     *
     * @param id 任务项ID
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/2/25
     */
    @RequestMapping(value = "/return/{id}", method = {RequestMethod.POST})
    public String returnTransmitByPath(@PathVariable String id) {
        return service.cancelTransmit(id, false);
    }

    /***
     *获取指定任务项的检查表
     * 如指定执行记录ID，获取执行记录对应的检查表和检查记录
     * 如为指定执行记录，根据任务项和单元获取适用的检查表
     *
     * @param dto 获取使用的条件
     * @return qc.module.ehs.dto.taskitem.TaskItemCheckTableResultDto
     * @author QuCheng Tech
     * @since 2025/1/16
     */
    @RequestMapping(value = "/checktable", method = {RequestMethod.GET, RequestMethod.POST})
    public TaskItemCheckTableResultDto getTaskItemCheckTable(@RequestBody TaskItemCheckTableConditionDto dto) throws QCPromptException {
        if (dto == null)
            throw new QCPromptException("获取数据的条件对象不能为空");
        if (StringUtils.isBlank(dto.getItemid()))
            throw new QCPromptException("获取数据的条件中任务项ID不能为空");
        if (StringUtils.isBlank(dto.getUnitid()))
            throw new QCPromptException("获取数据的条件中单元ID不能为空");

        //获取任务项信息
        TaskItemInfoDto taskitem = service.get(dto.getItemid(), 0x0, null);
        if (taskitem == null)
            throw new QCPromptException("根据指定的任务项获取到的信息为空");
        //获取任务信息，需要任务信息中的检查表配置信息
        TaskInfoDto taskinfo = taskInfoService.getTaskInfo(taskitem.getTaskid());
        if (taskinfo == null)
            throw new QCPromptException("根据指定的任务项获取到的任务信息为空");
        //判断如果任务信息中设置为不需要填写检查表，进行错误提示
        if (taskinfo.isNeedchecktable() == false)
            throw new QCPromptException("当前任务不需要填写检查表");
        if (taskinfo.getChecktableids() == null || taskinfo.getChecktableids().length < 0x1)
            throw new QCPromptException("当前任务没有配置任何检查表");
        //获取单元信息
        EhsUnitDto unit = unitInfoService.get(dto.getUnitid());
        if (unit == null)
            throw new QCPromptException("根据指定的单元取到的信息为空");

        //传入参数单元对应的检查表
        CheckTableDto destUnitCheckTable = null;
        //获取检查表集合
        for (String tableid : taskinfo.getChecktableids()) {
            CheckTableDto checktable = checkTableService.get(tableid);
            //逐个查询是否是当前单元匹配的检查表，如果是则直接返回
            if (checktable != null) {
                //判断如果检查表中指定了适用的单元集合是否包含当前单元；如果没有单元集合判断单元分类是否为当前单元
                if (checktable.getUnitids() != null && checktable.getUnitids().length > 0x0) {
                    if (Arrays.stream(checktable.getUnitids()).anyMatch(p -> StringUtils.equalsIgnoreCase(p, unit.getUnitid()))) {
                        destUnitCheckTable = checktable;
                        break;
                    }
                } else {
                    //判断单元分类
                    if (StringUtils.equalsIgnoreCase(checktable.getUccd(), unit.getUccd())) {
                        destUnitCheckTable = checktable;
                        break;
                    }
                }
            }
        }
        if (destUnitCheckTable == null)
            throw new QCPromptException("根据当前选择的单元没有任何匹配的检查表");

        TaskItemCheckTableResultDto result = new TaskItemCheckTableResultDto();
        //获取完整的检查表信息
        result.setTable(checkTableService.getTableFull(destUnitCheckTable.getTableid()));

        //判断是否有执行记录ID，如果有需要获取执行记录，判断单元是否变化、单元分类是否变化--确定使用的检查表是否要更新
        if (StringUtils.isNotBlank(dto.getExecid())) {
            //已有执行记录ID，根据执行记录中单元ID和本次的单元ID进行对比--变化和不变化不同处理
            TaskExecuteInfoDto taskexec = taskExecService.get(dto.getExecid());
            if (taskexec == null)
                throw new QCPromptException("根据指定的任务执行记录获取到的信息为空");
            if (StringUtils.isNotBlank(taskexec.getCheckrecordid())) {
                CheckRecordDto checkRecord = checkRecordService.get(taskexec.getCheckrecordid());
                if (checkRecord != null) {
                    //先使用已有执行记录中的检查记录作为返回结果中的检查记录
                    result.setRecord(checkRecord);
                    //获取执行记录中的单元
                    if (StringUtils.isNotBlank(taskexec.getUnitid())) {
                        if (StringUtils.equalsIgnoreCase(taskexec.getUnitid(), unit.getUnitid()) == false) {
                            //已有的执行记录中的单元与本次的目标单元ID不一致，判断单元分类是否变化
                            EhsUnitDto checkRecordUnit = unitInfoService.get(taskexec.getUnitid());
                            if (checkRecordUnit != null) {
                                if (StringUtils.equalsIgnoreCase(checkRecordUnit.getUccd(), unit.getUccd()) == false) {
                                    //单元ID不同，所属单元分类也不同；单元分类不同所使用的检查表也不同，此时不能将已有的检查记录返回
                                    result.setRecord(null);
                                }
                            }
                        }
                    }
                }
            }
        }

        return result;
    }

    /***
     * 对指定的任务项生成报告；不管是否已有报告文件，均进行1次生成报告；如原无报告文件生成后将报告文件ID进行赋值更新，如原已有报告文件重新生成并覆盖已有的文件（报告文件ID不更新）；
     *
     * @param id 任务项ID
     * @return 报告文件ID
     * @author QuCheng Tech
     * @since 2025/3/5
     */
    @RequestMapping(value = "/generaterpt", method = {RequestMethod.GET, RequestMethod.POST})
    public int generateReportByParam(@RequestParam(required = true) String id) throws QCPromptException {
        return generateTaskItemReportWord(id);
    }

    /***
     * 对指定的任务项生成报告；不管是否已有报告文件，均进行1次生成报告；如原无报告文件生成后将报告文件ID进行赋值更新，如原已有报告文件重新生成并覆盖已有的文件（报告文件ID不更新）；
     *
     * @param id 任务项ID
     * @return 报告文件ID
     * @author QuCheng Tech
     * @since 2025/3/5
     */
    @RequestMapping(value = "/generaterpt/{id}", method = {RequestMethod.GET, RequestMethod.POST})
    public int generateReportByPath(@PathVariable(required = true) String id) throws QCPromptException {
        return generateTaskItemReportWord(id);
    }

    /**
     * 生成word文件，将文件信息保存到文件信息表中，返回任务项对应的报告文件ID
     * @param taskItemId 任务项ID
     * @return int
     * @author QuCheng Tech
     * @since 2025/3/6
     */
    public int generateTaskItemReportWord(String taskItemId) throws QCPromptException {
        if (StringUtils.isBlank(taskItemId))
            throw new QCPromptException("生成任务项报告时指定的任务项ID不能为空");
        int reportFileId = 0x0;//最终返回隐患治理对应的报告文件ID

        EhsTaskItem taskItemEntity = service.getEntity(taskItemId);
        if (taskItemEntity == null)
            throw new QCPromptException("生成任务项报告时指定的任务项信息不存在");

        //如果已有报告文件ID，获取已经的文件ID
        if (taskItemEntity.getRptid() != null && taskItemEntity.getRptid().intValue() > 0x0)
            reportFileId = taskItemEntity.getRptid().intValue();

        //生成的word报告完整路径，包括目录和文件名
        String wordFileFullPath = generateTaskItemReportWordFile(taskItemEntity);

        //保存文件信息表中的信息
        FileSaveDto reportFileInfo = new FileSaveDto();
        reportFileInfo.setId(reportFileId);
        reportFileInfo.setPath(wordFileFullPath);
        //reportFileInfo.setTitle(destFileName);//与传入path中的文件名相同，可以不重复传入
        reportFileInfo.setSystem("ehs");
        reportFileInfo.setModule("TaskItemReport");

        //调用平台接口保存文件信息
        int saveFileResultId = restTemplatePlatform.saveFileInfo(reportFileInfo);
        //如果已有的文件ID为0，将调用平台保存文件信息接口返回的文件ID赋值给返回的文件ID
        if (reportFileId == 0x0) {
            reportFileId = saveFileResultId;
            //将保存文件信息返回的文件ID更新到隐患治理表中的报告文件ID
            String updateReportResult = service.updateReport(taskItemId, saveFileResultId);
            if (StringUtils.isNotBlank(updateReportResult))
                throw new QCPromptException(updateReportResult);
        }

        return reportFileId;
    }

    /**
     * 根据传入的任务项Entity生成任务项报告文件，返回生成的报告文件完整路径
     * 由于需要调用platform中的文件接口获取图片文件的完整路径，因此该方法不能放到service中
     * @param taskItemEntity 任务项Entity
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/3/18
     */
    public String generateTaskItemReportWordFile(EhsTaskItem taskItemEntity) throws QCPromptException {
        if (taskItemEntity == null)
            throw new QCPromptException("生成任务项报告时指定的任务项信息不存在");
        //存放要填充的数据
        Map<String, Object> datas = new HashMap<String, Object>();

        String generateWordFileName = "安全生产检查记录单";
        //输出为文件，指定输出文件名
        String fileUploadPath = UPLOAD_PATH + QCConstant.ROUTE_SPLIT;
        String templateFileName = "安全生产检查记录单-模板.docx";
        String fileDownloadPath = DOWNLOAD_PATH + QCConstant.ROUTE_SPLIT;
        //文件名使用隐患标题
        String destFileName = generateWordFileName + "-" + taskItemEntity.getItemname() + ".docx";
        try {
            //任务项基本信息
            //任务项执行记录：可能1个任务项有多个执行记录，获取最后1个执行记录中的执行文字、状态和附件
            datas.put("任务名称", Texts.of(taskItemEntity.getItemname()).create());
            //如果有设备设施或危险源名称，加上设备设施和危险源名称
            String unitName = "";
            if (StringUtils.isNotBlank(taskItemEntity.getUnitname()))
                unitName = taskItemEntity.getUnitname();
            if (StringUtils.isNotBlank(taskItemEntity.getFacilityname()))
                unitName += taskItemEntity.getFacilityname();
            if (StringUtils.isNotBlank(taskItemEntity.getHazardname()))
                unitName += taskItemEntity.getHazardname();
            datas.put("单元", Texts.of(unitName).create());

            datas.put("计划时间", Texts.of(taskItemEntity.getPlantmstr()).create());
            if (taskItemEntity.getHasfinish() == true)
                datas.put("是否完成", Texts.of("已完成").create());
            else
                datas.put("是否完成", Texts.of("未完成").create());

            //需要从执行记录中获取信息进行赋值的属性
            List<EhsTaskExec> taskExecutes = taskExecService.getTaskItemExecuteEntitys(taskItemEntity.getItemid());
            if (taskExecutes != null && taskExecutes.size() > 0x0) {
                //获取最后一条执行记录，使用最后一条执行记录中的信息
                EhsTaskExec lastExecute = taskExecutes.get(taskExecutes.size() - 0x1);

                if (lastExecute != null) {
                    if (lastExecute.getIsnormal() == true)
                        datas.put("是否异常", Texts.of("正常").create());
                    else
                        datas.put("是否异常", Texts.of("异常").create());
                    datas.put("执行时间", Texts.of(lastExecute.getExecutetmstr()).create());
                    datas.put("执行人员", Texts.of(lastExecute.getExecutor()).create());
                    datas.put("确认人", Texts.of(lastExecute.getConfirmusername()).create());

                    datas.put("执行内容描述", Texts.of(lastExecute.getExecdescription()).create());
                    //检查附件中获取照片，默认获取第1张
                    String correctImageFileName = getImageFullName(lastExecute.getExecattachment());
                    if (StringUtils.isNotBlank(correctImageFileName))
                        datas.put("检查照片", Pictures.ofLocal(correctImageFileName).create());
                    //检查人签字图片
                    if (StringUtils.isNotBlank(lastExecute.getExecsign())) {
                        //签字的属性数据为对应签字图片id
                        try {
                            int fileId = Integer.parseInt(lastExecute.getExecsign());
                            try {
                                FileInfoDto fileinfo = restTemplatePlatform.getFileById(fileId);

                                if (fileinfo != null) {
                                    String fileFullName = fileinfo.getPath() + QCConstant.ROUTE_SPLIT + fileinfo.getName() + "." + fileinfo.getExtension();
                                    datas.put("检查人签字", Pictures.ofLocal(fileFullName).create());
                                }
                            } catch (QCPromptException e) {
                                e.printStackTrace();
                            }
                        } catch (NumberFormatException e) {
                            e.printStackTrace();
                        }
                    }
                    if (lastExecute.getIntm() != null)
                        datas.put("检查人签字日期", Texts.of(DateUtil.getDateString(lastExecute.getIntm())).create());

                    datas.put("确认情况", Texts.of(lastExecute.getConfirmdescription()).create());
                    //确认人签字图片
                    if (StringUtils.isNotBlank(lastExecute.getConfirmsign())) {
                        //签字的属性数据为对应签字图片id
                        try {
                            int fileId = Integer.parseInt(lastExecute.getConfirmsign());
                            try {
                                FileInfoDto fileinfo = restTemplatePlatform.getFileById(fileId);

                                if (fileinfo != null) {
                                    String fileFullName = fileinfo.getPath() + QCConstant.ROUTE_SPLIT + fileinfo.getName() + "." + fileinfo.getExtension();
                                    datas.put("确认人签字", Pictures.ofLocal(fileFullName).create());
                                }
                            } catch (QCPromptException e) {
                                e.printStackTrace();
                            }
                        } catch (NumberFormatException e) {
                            e.printStackTrace();
                        }
                    }
                    if (lastExecute.getConfirmtm() != null)
                        datas.put("确认人签字日期", Texts.of(DateUtil.getDateString(lastExecute.getConfirmtm())).create());

                    //生成报告附件表格
                    TableRenderData attachmentTable = generateAttachmentTable(lastExecute.getCheckrecordid());
                    if (attachmentTable != null) {
                        datas.put("附件表格", attachmentTable);
                    }
                }
            }

            XWPFTemplate.compile(fileUploadPath + templateFileName).render(datas).writeToFile(fileDownloadPath + destFileName);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //返回完整的文件路径；包含文件目录+文件名
        return fileDownloadPath + destFileName;
    }


    /**
     * 生成报告的附件表格 返回null说明没有附件
     * @param checkrecordId 检查记录id
     * @return TableRenderData 表格数据
     */
    public TableRenderData generateAttachmentTable(String checkrecordId) {
        //验证参数
        if (StringUtils.isBlank(checkrecordId)) return null;

        CheckRecordDto checkRecordDto = checkRecordService.get(checkrecordId);

        if (Objects.nonNull(checkRecordDto) && StringUtils.isNotBlank(checkRecordDto.getContent())) {
            //解析Json字符串
            JSONObject recordContent = JsonUtil.toJSONObject(checkRecordDto.getContent());

            if (recordContent != null) {
                //获取content和schema部分
                JSONObject content = recordContent.getJSONObject("content");
                JSONArray schema = recordContent.getJSONArray("schema");
                if (content != null && schema != null && !content.isEmpty() && !schema.isEmpty()) {
                    //创建行列表
                    List<RowRenderData> rows = new ArrayList<>();

                    //创建表头行
                    RowRenderData headerRow = Rows.of("序号", "检查项目", "检查内容", "检查结果", "备注", "附件")
                            .verticalCenter()
                            .center()
                            .textBold()
                            .textFontFamily("宋体")
                            .textColor("000000")
                            .bgColor("e3e3e3")
                            .rowAtleastHeight(2.0)
                            .create();
                    //添加列表头
                    rows.add(headerRow);

                    // 创建一个共享的Builder，用于处理合并单元格规则
                    MergeCellRule.MergeCellRuleBuilder builder = MergeCellRule.builder();

                    //记录当前索引
                    int rowIndex = 1;

                    //记录当前处理的分组信息
                    String currentGroupName = null;
                    int groupStartRow = -1;
                    int groupItemCount = 0;

                    //遍历schema，处理表格内容
                    for (int i = 0; i < schema.size(); i++) {
                        JSONObject item = schema.getJSONObject(i);
                        String component = item.getString("component");

                        //处理分组标题，标题跳过不进行处理
                        if ("Divider".equals(component)) {
                            //调用合并规则
                            processGroupMerge(builder, groupStartRow, groupItemCount);
                            //记录新分组信息
                            currentGroupName = item.getString("field");
                            //记录当前索引
                            groupStartRow = rowIndex;
                            //重置计数器器
                            groupItemCount = 0;
                            continue;
                        }

                        //处理检查项
                        String field = item.getString("field");

                        //只处理有对应内容的字段
                        if (content.containsKey(field)) {
                            JSONObject fieldData = content.getJSONObject(field);
                            if (fieldData != null) {
                                String value = fieldData.getString("value");
                                String description = fieldData.getString("description");
                                String images = fieldData.getString("images");

                                //创建检查行
                                RowRenderData itemRow = Rows.of(
                                        String.valueOf(item.getString("index")),
                                        currentGroupName,
                                        field,
                                        value,
                                        description,
                                        ""
                                ).verticalCenter().center().create();
                                rows.add(itemRow);
                                groupItemCount++;
                                rowIndex++;

                                //处理图片
                                processImages(rows, images, rowIndex);
                            }
                        }
                    }
                    // 在处理完所有项目后，处理最后一个分组
                    processGroupMerge(builder, groupStartRow, groupItemCount);

                    // 1. 首先将所有行转换为数组
                    RowRenderData[] rowArray = rows.toArray(new RowRenderData[0]);

                    // 2. 创建一个表格
                    TableRenderData tableRenderData = Tables.of(rowArray)
                            .center()
                            .border(BorderStyle.DEFAULT)  // 添加边框样式
                            .create();

                    // 构建一个包含所有映射的规则对象
                    MergeCellRule completeRule = builder.build();
                    // 一次性设置所有规则
                    tableRenderData.setMergeRule(completeRule);
                    // 4. 返回这个表格
                    return tableRenderData;
                }
            }
        }
        return null;
    }

    /**
     * 处理分组
     * @param builder   mergeCellRuleBuider的构建器，用于收集合并规则
     * @param startRow  分组的其实索引行
     * @param itemCount 分组合并的数量行
     */
    private void processGroupMerge(MergeCellRule.MergeCellRuleBuilder builder, int startRow, int itemCount) {
        if (startRow >= 0 && itemCount > 1) {
            MergeCellRule.Grid from = MergeCellRule.Grid.of(startRow, 1);
            MergeCellRule.Grid to = MergeCellRule.Grid.of(startRow + itemCount - 1, 1);
            // 确保from和to不同，且在有效范围内
            builder.map(from, to);
        }
    }

    /**
     * 处理json图片数组，并添加到表格中
     * @param rows     表格行
     * @param images   json图片数组
     * @param rowIndex 当前行索引
     */
    private void processImages(List<RowRenderData> rows, String images, int rowIndex) {
        if (StringUtils.isNotBlank(images)) {
            //获取当前检查行
            RowRenderData currentRow = rows.get(rowIndex - 1);

            //创建单元格并替换当前行的附件单元格
            Cells.CellBuilder cellBuilder = Cells.of();

            //直接使用字符串作为参数
            String imageFullName = getImageFullName(images);
            if (StringUtils.isNotBlank(imageFullName) && imageFullName != null) {
                //创建图片单元格
                PictureRenderData pictureData = Pictures.ofLocal(imageFullName).size(80, 60).create();
                //添加段落
                cellBuilder.addParagraph(pictureData);
            }

            //创建单元格并替换当前附件单元格
            CellRenderData renderData = cellBuilder.center().create();

            //替换附件单元格
            currentRow.getCells().set(currentRow.getCells().size() - 1, renderData);
        }
    }

    /***
     * 根据输入的附件或文件json字符串得到图片完整路径和名称
     *
     * @param jsonString 附件或文件json字符串
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/1/19
     */
    String getImageFullName(String jsonString) {
        if (StringUtils.isNotBlank(jsonString)) {
            QcAttachementFile[] files = QcAttachementsUtil.resolve(jsonString);
            if (files != null && files.length > 0x0) {
                //附件只显示1张图片，判断文件类型是图片显示第1张图片文件
                for (QcAttachementFile file : files) {
                    //要求文件ID和type不为空
                    if (file.id > 0x0 && StringUtils.isNotBlank(file.type)) {
                        if (StringUtils.equalsIgnoreCase(file.getType(), "jpg") || StringUtils.equalsIgnoreCase(file.getType(), "jpeg") || StringUtils.equalsIgnoreCase(file.getType(), "png")) {
                            //根据文件ID获取文件的完整路径和名称，调用platform中的接口
                            try {
                                FileInfoDto fileinfo = restTemplatePlatform.getFileById(file.id);

                                if (fileinfo != null) {
                                    String fileFullName = fileinfo.getPath() + QCConstant.ROUTE_SPLIT + fileinfo.getName() + "." + fileinfo.getExtension();

                                    return fileFullName;
                                }
                            } catch (QCPromptException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }

        return null;
    }

    /***
     *对指定的任务项上传报告，不管是否已存在报告文件；
     *
     * @param dto 更新任务项报告DTO
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/3/5
     */
    @RequestMapping(value = "/uploadreport", method = {RequestMethod.POST})
    public String uploadReport(@RequestBody EhsReportFileUpdateDto dto) {
        if (dto == null)
            return QCUnifyReturnValue.Warn("上传的任务项报告对象不能为空");
        if (StringUtils.isBlank(dto.getId()))
            return QCUnifyReturnValue.Warn("上传的任务项报告信息中隐患治理ID不能为空");
        if (dto.getFileid() < 0x1)
            return QCUnifyReturnValue.Warn("上传的任务项报告信息中报告文件ID无效");

        return service.updateReport(dto.getId(), dto.getFileid());
    }
}
